package tdt4240.iddqd;

import java.util.List;

import org.anddev.andengine.entity.sprite.AnimatedSprite;
import org.anddev.andengine.opengl.texture.region.TiledTextureRegion;

import tdt4240.iddqd.sprites.*;

public abstract class MapFactory {

	protected int currentLevelId = 1;
	protected int currentCheckpointId = 0;

	public MapFactory() {

	}

	public MapFactory(int startingLevelId, int startingCheckpointId) {
		currentLevelId = startingLevelId;
		currentCheckpointId = startingCheckpointId;
	}

	public abstract Map getCurrentMap();

	/**
	 * Create a map instance from a list of sprites
	 * @param sprites List of sprites to be included in map
	 * @return A map instance
	 */
	protected Map createMapFromSprites(List<AnimatedSprite> sprites) {
		Map map = new Map(currentLevelId);

		//Fill map lists and set player
		for(AnimatedSprite element : sprites) {
			if(element != null) {
				if(element instanceof Player)
					map.player = (Player)element;
				else if(element instanceof Enemy)
					map.enemies.add((Enemy)element);
				else if(element instanceof Landscape)
					map.landscape.add((Landscape)element);
				else if(element instanceof Checkpoint)
					map.checkpoints.add((Checkpoint)element);
			}
		}
		
		//Set correct player position if continuing from previous progress
		if(currentCheckpointId > 0) {
			for(Checkpoint cp : map.checkpoints) {
				if(cp.id == currentCheckpointId) {
					map.player.setPosition(cp.centerX(), cp.centerY());
					break;
				}
			}
		}

		return map;
	}

	/**
	 * Creates a instance of a sprite class (all inherit from from AnimatedSprite) based on an ID and a list of parameters
	 * @param id The ID of the desired sprite type
	 * @param parameters The list of parameters which will vary in length depending on the type
	 * @return A sprite instance
	 */
	protected AnimatedSprite createSpriteFromId(String id, int[] parameters) {
		AnimatedSprite sprite = null;

		if(id.equals(Constants.LANDSCAPE_WALL)) { // Wall
			TiledTextureRegion wall = GameActivity.mHedge.deepCopy();
			wall.setWidth((int)(GameActivity.mHedgeTextureAtlas.getWidth() * (parameters[2] / (double)GameActivity.mHedgeTextureAtlas.getWidth()) / Constants.STRETCH_WALL));
			wall.setHeight((int)(GameActivity.mHedgeTextureAtlas.getHeight() * (parameters[3] / (double)GameActivity.mHedgeTextureAtlas.getHeight()) / Constants.STRETCH_WALL));
			sprite = new Landscape(parameters[0], parameters[1], parameters[2], parameters[3], wall);
		}
		else if(id.equals(Constants.LANDSCAPE_PLANT)) { // Plant
			sprite = new Landscape(parameters[0], parameters[1], parameters[2], parameters[3], GameActivity.mPlant);
		}
		else if(id.equals(Constants.LANDSCAPE_FLOWER)) { // Flower
			sprite = new Landscape(parameters[0], parameters[1], parameters[2], parameters[3], GameActivity.mFlower);
		}
		else if(id.equals(Constants.PLAYER)) { // Player
			sprite = new Player(parameters[0], parameters[1], GameActivity.mPlayerWalk);
		}
		else if(id.equals(Constants.CHECKPOINT_INTERMEDIATE)) { // Intermediate checkpoint
			sprite = new Checkpoint(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], false, GameActivity.mBlank);
		}
		else if(id.equals(Constants.CHECKPOINT_END)) { // End of level checkpoint
			sprite = new Checkpoint(parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], true, GameActivity.mBlank);
		}
		else if(id.startsWith(Constants.ENEMY_PREFIX)){ // Some enemy
			sprite = EnemyFactory.createEnemy(parameters[0], parameters[1], id);
		}

		return sprite;
	}

	/**
	 * Convert a line from a level file into pieces and parse these into a sprite
	 * @param line A line from a level file
	 * @return A sprite instance
	 */
	protected AnimatedSprite parseLine(String line) {
		String[] pieces = line.split(" ");
		String[] parameters = pieces[1].split(",");
		int[] intParameters = new int[parameters.length];
		for(int i = 0; i < parameters.length; i++)
			intParameters[i] = Integer.parseInt(parameters[i]);
		return createSpriteFromId(pieces[0], intParameters);
	}
}
